<?php
/**
 * Created by PhpStorm.
 * User: gyq
 * Date: 2018/11/5
 * Time: 21:12
 */

namespace app\api\service;


use app\api\model\User;
use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;
use app\lib\exception\weChatException;
use think\Exception;
use think\facade\Cache;

class UserToken extends Token
{
    protected $code;
    protected $appid;
    protected $appSecret;
    protected $loginUrl;

    public function __construct($code)
    {
        $this->code = $code;
        $this->appid = config('wx.appid');
        $this->appSecret = config('wx.appSecret');
        $this->loginUrl = sprintf(config('wx.loginUrl'), $this->appid, $this->appSecret, $this->code);
    }

    public function get()
    {
        $res = curl_get($this->loginUrl);
//        true 为 字符串转换成数组，false为转换成对象
        $wxResult = json_decode($res, true);
        if (empty($wxResult)) {
            throw new Exception('获取session_key及openID时异常，微信内部错误');
        } else {
            $loginFail = array_key_exists('errcode', $wxResult);
            if ($loginFail) {
                throw new weChatException([
                    'errorcode' => $wxResult['errcode'],
                    'msg' => $wxResult['errmsg']
                ]);
            } else {
                return $this->grantToken($wxResult);
            }
        }
    }
    // 生成令牌
    // key：令牌
    // value：wxResult，uid，scope
    private function grantToken($wxResult)
    {
        $openid = $wxResult['openid'];
        $user = User::getByOpenID($openid);
        if ($user) {
            $uid = $user->id;
        } else {
            $uid = $this->newUser($openid);
        }
        $cacheValue = $this->prepareCacheValue($wxResult, $uid);
        $token = $this->saveToCache($cacheValue);
        return $token;
    }

    private function saveToCache($cacheValue)
    {
        $key = $this->generateToken();
        $value = json_encode($cacheValue);
        $expire = config('setting.token_expire_in');
        $request = Cache::set($key,$value,$expire);
        if (!$request) {
            throw new TokenException([
                'msg' => '服务器缓存异常',
                'errorcode' => 10005
            ]);
        }
        return $key;
    }

//scope 跟权限有关
//缓存
    private function prepareCacheValue($wxResult, $uid)
    {
        $cacheValue = $wxResult;
        $cacheValue['uid'] = $uid;
        $cacheValue['scope'] = ScopeEnum::User;
        return $cacheValue;
    }

    private function newUser($openid)
    {
        $user = User::create([
            'openid' => $openid
        ]);
        return $user->id;
    }
}